package com.jwds.digital.bios.business.service.service.belt.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwds.digital.bios.business.core.exceptions.RecordNotFoundException;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.BeltRouteTaskBeltDetailReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.assembler.BeltRouteTaskBeltDetailAssembler;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTaskBeltDetail;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltRouteTaskBeltDetailMapper;
import com.jwds.digital.bios.business.core.infrastructure.vo.belt.BeltRouteTaskBeltDetailRespVO;
import com.jwds.digital.bios.business.service.service.belt.IBeltRouteTaskBeltDetailService;
import com.jwds.tdc.framework.application.lib.page.PageRequest;
import com.jwds.tdc.framework.application.lib.page.PageResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 路线作业实绩皮带详情表实现类
 * @author 林柏云
 * @date 2024-12-05
 */
@Slf4j
@Service
public class BeltRouteTaskBeltDetailServiceImpl extends ServiceImpl<BeltRouteTaskBeltDetailMapper, BeltRouteTaskBeltDetail> implements IBeltRouteTaskBeltDetailService {

  @Autowired
  private BeltRouteTaskBeltDetailMapper baseMapper;

  @Override
  public BeltRouteTaskBeltDetailRespVO queryById(Long id) {
    if(id == null) {
      return null;
    }
    BeltRouteTaskBeltDetail entity = baseMapper.selectById(id);
    return BeltRouteTaskBeltDetailAssembler.entity2dto(entity);
  }

  @Override
  public PageResponse<BeltRouteTaskBeltDetailRespVO> page(PageRequest<BeltRouteTaskBeltDetailReqDTO> request) {
    BeltRouteTaskBeltDetailReqDTO condition = request.getQueryCondition();
    Page<BeltRouteTaskBeltDetailRespVO> page = new Page<>(request.getPageIndex(), request.getPageSize());
    IPage<BeltRouteTaskBeltDetailRespVO> pageData = baseMapper.pageQuery(page, condition);
    return new PageResponse<>((Page<?>)pageData, pageData.getRecords());
  }

  @Override
  public List<BeltRouteTaskBeltDetailRespVO> list(BeltRouteTaskBeltDetailReqDTO reqDto) {
    return baseMapper.queryList(reqDto);
  }

  @Override
  public void add(BeltRouteTaskBeltDetailReqDTO reqDto) {
    BeltRouteTaskBeltDetail entity = BeltRouteTaskBeltDetailAssembler.dto2entity(reqDto);
    baseMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchAdd(List<BeltRouteTaskBeltDetailReqDTO> dtoList) {
    dtoList.forEach(this::add);
  }

  @Override
  public void update(BeltRouteTaskBeltDetailReqDTO reqDto) {
    BeltRouteTaskBeltDetail oldEntity = baseMapper.selectById(reqDto.getId());
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    BeltRouteTaskBeltDetail newEntity = BeltRouteTaskBeltDetailAssembler.dto2entity(reqDto, oldEntity);
    baseMapper.updateById(newEntity);
  }

  @Override
  public void delete(Long id) {
    BeltRouteTaskBeltDetail oldEntity = baseMapper.selectById(id);
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    baseMapper.deleteById(id);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchDelete(List<Long> ids) {
    for (Long id : ids) {
      delete(id);
    }
  }

  @Override
  public List<BeltRouteTaskBeltDetailRespVO> getTransportRouteDetails(Integer routeId) {

    // 对应线路所有电机的运输情况
    List<BeltRouteTaskBeltDetailRespVO> beltRouteTaskBeltDetailRespVOList = baseMapper.getTransportRouteDetails(routeId, DateUtil.beginOfDay(new Date()));

    // 根据belt_code分组
    Map<String, List<BeltRouteTaskBeltDetailRespVO>> groupedByBeltCode = beltRouteTaskBeltDetailRespVOList.stream()
            .collect(Collectors.groupingBy(BeltRouteTaskBeltDetailRespVO::getBeltCode));

    List<BeltRouteTaskBeltDetailRespVO> beltRouteTaskBeltDetailRespVOS = new ArrayList<>();

    groupedByBeltCode.forEach((code,entry)-> {

      BeltRouteTaskBeltDetailRespVO beltRouteTaskBeltDetailRespVO = new BeltRouteTaskBeltDetailRespVO();

      List<BeltRouteTaskBeltDetailRespVO> beltDetailRespVOS = new ArrayList<>();
      AtomicInteger count = new AtomicInteger();

      entry.stream().forEach(detail -> {
        BeltRouteTaskBeltDetailRespVO beltDetailRespVO = new BeltRouteTaskBeltDetailRespVO();

        beltDetailRespVO.setOperationEfficiency(detail.getOperationEfficiency());
        beltDetailRespVO.setAvgAllLoadRate(detail.getAvgAllLoadRate());
        beltDetailRespVO.setCreateTime(detail.getCreateTime());
        beltDetailRespVOS.add(beltDetailRespVO);

        // 累加每个电机的能耗
        beltRouteTaskBeltDetailRespVO.setTonPowerConsumption(
                Optional.ofNullable(beltRouteTaskBeltDetailRespVO.getTonPowerConsumption())
                        .orElse(BigDecimal.ZERO)
                        .add(detail.getTonPowerConsumption())
        );

        // 累加每个电机的运行时长
        BigDecimal runningTime = Optional.ofNullable(beltRouteTaskBeltDetailRespVO.getRunningTime())
                .orElse(BigDecimal.ZERO)
                .add(detail.getRunningTime());
        // 转换为小时，保留两位小数
        beltRouteTaskBeltDetailRespVO.setRunningTime(runningTime.divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP));

        // 获取每个电机的负载次数
        if (detail.getLoadRunningTime().compareTo(BigDecimal.ZERO) > 0) {
          count.incrementAndGet();
        }

        // 累加每个电机的运行效率
        beltRouteTaskBeltDetailRespVO.setOperationEfficiency(
                Optional.ofNullable(beltRouteTaskBeltDetailRespVO.getOperationEfficiency())
                        .orElse(BigDecimal.ZERO)
                        .add(detail.getOperationEfficiency())
        );
      });
      beltRouteTaskBeltDetailRespVO.setBeltCode(code);
      beltRouteTaskBeltDetailRespVO.setAlarmInformation(baseMapper.getAlarmInformation(entry.get(entry.size()-1).getTaskId(), entry.get(entry.size()-1).getFlowNo()));
      beltRouteTaskBeltDetailRespVO.setBeltRouteTaskBeltDetailRespVOS(beltDetailRespVOS);
      beltRouteTaskBeltDetailRespVO.setAvgAllLoadRate(BigDecimal.valueOf(count.get() / entry.size()));
      beltRouteTaskBeltDetailRespVO.setOperationEfficiency(
              beltRouteTaskBeltDetailRespVO.getOperationEfficiency().divide(BigDecimal.valueOf(entry.size()), BigDecimal.ROUND_HALF_UP));

      beltRouteTaskBeltDetailRespVOS.add(beltRouteTaskBeltDetailRespVO);
    });

    return beltRouteTaskBeltDetailRespVOS;
  }

}
